package com.im.utils.Redis.RedisBatch;

import com.im.constant.RedisConstant;
import org.springframework.beans.factory.annotation.*;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.*;

@Component
public class RedisBatchSequenceGenerator {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private RedisScriptManager redisScriptManager;

    /**
     * 使用 pipeline 一次批量调用单条 Lua 脚本生成序列号
     * @param sessionId 会话ID
     * @param batchSize 批量数量，例如 100
     * @return 批量生成的序列号列表
     */
    public List<Long> getNextSequencesPipeline(Long sessionId, int batchSize) {
        final String redisKey = RedisConstant.SESSION_MESSAGE_ID_PREFIX + sessionId;
        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
        byte[] keyBytes = serializer.serialize(redisKey);
        final byte[] shaBytes = redisScriptManager.getScriptSha().getBytes(StandardCharsets.UTF_8);

        // 使用 pipeline 执行多个命令
        List<Object> results = redisTemplate.executePipelined(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                for (int i = 0; i < batchSize; i++)
                    connection.evalSha(shaBytes, ReturnType.INTEGER, 1, keyBytes);
                return null;// 返回 null，pipeline 会自动收集所有返回值
            }
        });

        // 将返回值转换为 List<Long>
        List<Long> seqList = new ArrayList<>();
        if (results != null)
            for (Object result : results)
                if (result != null) {
                    try {seqList.add(Long.valueOf(result.toString()));}
                    catch (NumberFormatException e) {/** 如果转换异常，可记录日志后忽略或抛出异常**/}
                }
        return seqList;
    }
}
